package cn.b.sky.mes.cm.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import cn.b.sky.mes.cm.dao.BOMComponentDao;
import cn.b.sky.mes.cm.dao.BOMDao;
import cn.b.sky.mes.cm.model.BOM;
import cn.b.sky.mes.cm.model.BOMComponent;
import cn.b.sky.mes.cm.model.Material;
import cn.b.sky.mes.cm.model.condition.BOMCondition;
import cn.b.sky.mes.cm.service.BOMService;
import cn.b.sky.common.model.BatchJobReport;
import cn.b.sky.common.utils.DatabaseUtils;
import cn.b.sky.i18n.utils.LocaleResourceBundle;
import cn.b.sky.user.SecurityContextUtil;

@Service("bomService")
public class BOMServiceImpl implements BOMService {

  private static final Logger LOGGER = LoggerFactory.getLogger(BOMServiceImpl.class);

  @Resource
  BOMDao bomDao;

  @Resource
  BOMComponentDao bomComponentDao;

  @Override
  public List<BOM> selectBOMListByCondition(BOMCondition condition) {
    if (StringUtils.isBlank(condition.getOrderField())) {
      condition.setOrderField("CreateDateTime");
    }
    return bomDao.selectBOMListByCondition(condition);
  }

  @Override
  public int selectBOMCountByCondition(BOMCondition condition) {
    return bomDao.selectBOMCountByCondition(condition);
  }

  @Override
  public void insertBOM(BOM bom) {
    if (StringUtils.isBlank(bom.getBomCode()) || StringUtils.isBlank(bom.getSiteCode())) {
      return;
    }
    bomDao.insertBOM(bom);
    for (BOMComponent component : bom.getComponents()) {
      if (component == null || StringUtils.isBlank(component.getComponentCode())) {
        continue;
      }
      setBaseInfo(bom, component);
      bomComponentDao.insertComponent(component);
    }

  }

  @Override
  public boolean updateBOM(BOM bom) {
    String bomCode = bom.getBomCode();
    String siteCode = bom.getSiteCode();
    if (StringUtils.isBlank(bom.getBomCode()) || StringUtils.isBlank(bom.getSiteCode())) {
      return true;
    }
    List<String> materialCodes = new ArrayList<String>();
    List<Material> list = this.selectMaterialByBomCode(bom.getBomCode(), bom.getSiteCode());
    this.recurseMaterials(materialCodes, list);
    List<BOMComponent> orgComponents = bomComponentDao.selectComponents(bomCode, siteCode);
    for (BOMComponent component : bom.getComponents()) {
      if (component != null && !StringUtils.isBlank(component.getComponentCode())) {
        if (materialCodes.indexOf(component.getComponentCode()) != -1) {
          //不能循环嵌套
          return false;
        }
        if (orgComponents.contains(component)) {
          component.setModifyDateTime(bom.getModifyDateTime());
          component.setModifyUser(bom.getModifyUser());
          //更新已存在的
          bomComponentDao.updateComponent(component);
          orgComponents.remove(component);
        } else {
          setBaseInfo(bom, component);
          //插入新增的
          bomComponentDao.insertComponent(component);
        }
      }
    }
    for (BOMComponent component : orgComponents) {
      //删除本存在但被移除的
      bomComponentDao.deleteComponentById(component.getId());
      bom.getComponents().remove(component);
    }
    bomDao.updateBOM(bom);
    return true;

  }

  @Override
  public BatchJobReport deleteBOM(String bomCode, String siteCode) {
    if (!StringUtils.isBlank(bomCode)) {
      String message = bomCode;
      String cause = "";
      boolean success = true;
      try {
        bomComponentDao.deleteAllComponents(bomCode, siteCode);
        bomDao.deleteBOM(bomCode, siteCode);
      } catch (Exception e) {
        LOGGER.error("{}", e);
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        success = false;
        String errorMsg = e.getMessage();
        if (DatabaseUtils.isConstraintsError(errorMsg)) {
          //外键删除已存在提示
          errorMsg = LocaleResourceBundle.getCommonResourceLabel(SecurityContextUtil.getSiteCode(),SecurityContextUtil.getLanguageCode(),
              "dataBaseOperationPkFail.M")
              + LocaleResourceBundle.getCommonResourceLabel(SecurityContextUtil.getSiteCode(),SecurityContextUtil.getLanguageCode(), "notDelete.M");
        }
        cause = errorMsg;
      }
      return new BatchJobReport(message, cause, success, SecurityContextUtil.getLanguageCode(),SecurityContextUtil.getSiteCode());
    } else {
      return new BatchJobReport("", "id is null", false, SecurityContextUtil.getLanguageCode(),SecurityContextUtil.getSiteCode());
    }
  }

  @Override
  public BOM getBOMAndComponents(String bomCode, String siteCode) {
    if (StringUtils.isBlank(bomCode) || StringUtils.isBlank(siteCode)) {
      return null;
    }
    List<BOMComponent> components = bomComponentDao.selectComponents(bomCode, siteCode);
    BOM bom = bomDao.getBOM(bomCode, siteCode);
    bom.setComponents(components);
    return bom;
  }

  private void setBaseInfo(BOM bom, BOMComponent component) {
    component.setSiteCode(bom.getSiteCode());
    component.setBomCode(bom.getBomCode());
    component.setCreateDateTime(bom.getCreateDateTime());
    component.setCreateUser(bom.getCreateUser());
    component.setModifyDateTime(bom.getModifyDateTime());
    component.setModifyUser(bom.getModifyUser());
  }

  @Override
  public List<Material> selectMaterialByBomCode(String bomCode, String siteCode) {
    if (StringUtils.isBlank(bomCode) || StringUtils.isBlank(siteCode)) {
      return null;
    }
    return bomDao.selectMaterialByBomCode(bomCode, siteCode);
  }

  @Override
  public List<Material> selectMaterialByComponentCode(String materialCode, String siteCode) {
    if (StringUtils.isBlank(materialCode) || StringUtils.isBlank(siteCode)) {
      return null;
    }
    return bomDao.selectMaterialByComponentCode(materialCode, siteCode);
  }

  @Override
  public void recurseMaterials(List<String> materialCodes, List<Material> list) {
    if (list.size() > 0) {
      for (Material m : list) {
        materialCodes.add(m.getMaterialCode());
        List<Material> materialList = this.selectMaterialByComponentCode(m.getMaterialCode(), m.getSiteCode());
        recurseMaterials(materialCodes, materialList);
      }
    }
  }

  @Override
  public BOM getBOM(String bomCode, String siteCode) {
    return bomDao.getBOM(bomCode, siteCode);
  }

  @Override
  public List<BOMComponent> getBOMComponents(String bomCode, String siteCode) {
    return bomComponentDao.selectComponents(bomCode, siteCode);
  }

  @Override
  public List<BOMComponent> selectComponentsAndItsBomCode(String bomCode, String siteCode) {
    if (StringUtils.isBlank(bomCode) || StringUtils.isBlank(siteCode)) {
      return new ArrayList<BOMComponent>();
    }
    return bomDao.selectComponentsAndItsBomCode(bomCode, siteCode);
  }

  @Override
  public List<BOMComponent> getBOMComponentByBom(String siteCode, String bomCode) {

    return bomComponentDao.selectComponents(bomCode, siteCode);
  }

  @Override
  public List<BOM> selectBOMSuggests(BOMCondition condition) {
    return bomDao.selectBOMSuggests(condition);
  }

  @Override
  public List<BOMComponent> selectParentsComponents(String componentCode, String siteCode) {
    if (StringUtils.isBlank(componentCode) || StringUtils.isBlank(siteCode)) {
      return new ArrayList<BOMComponent>();
    }
    return bomDao.selectParentsComponents(componentCode, siteCode);
  }
}
